#include "tilelayer.hpp"
#include "util.hpp"
#include "tileset.hpp"

namespace nmc
{
	TileLayer::TileLayer(int width, int height, int fillTile)
	{
		mWidth = width;
		mHeight = height;
		mTiles = new unsigned short[width * height];
		clear(fillTile);
	}
			
	TileLayer::TileLayer(const TileLayer& other) 
	{
		mWidth = other.mWidth;
		mHeight = other.mHeight;
		mTiles = new unsigned short[mWidth * mHeight];

		for (int i = 0; i < mWidth*mHeight; i++)
		{
			mTiles[i] = other.mTiles[i];
		}
	}

	TileLayer::~TileLayer()
	{
		delete[] mTiles;
	}

	int TileLayer::getTile(int x, int y)
	{
		x = clamp(x, 0, mWidth - 1);
		y = clamp(y, 0, mHeight - 1);
		return mTiles[x + y * mWidth];
	}

	void TileLayer::setTile(int x, int y, int tile)
	{
		if (x < 0 
			|| x >= mWidth
			|| y < 0
			|| y >= mHeight)
		{
			return;
		}

		mTiles[x + y * mWidth] = tile;
	}

	void TileLayer::clear(int tile)
	{
		for (int i = 0; i < mWidth * mHeight; i++)
		{
			mTiles[i] = tile;
		}
	}

	int TileLayer::getWidth()
	{
		return mWidth;
	}

	int TileLayer::getHeight()
	{
		return mHeight;
	}

	TileLayer *TileLayer::clonePart(int x_, int y_, int width, int height)
	{
		TileLayer *newTileLayer = new TileLayer(width, height);

		for (int y = 0; y < height; y++)
		{
			for (int x= 0; x < width; x++)
			{
				newTileLayer->setTile(x, y, getTile(x + x_, y + y_));
			}
		}

		return newTileLayer;
	}

	void TileLayer::pastePart(TileLayer* tileLayer, int x_, int y_, bool transparency)
	{
		for (int y = 0; y < tileLayer->getHeight(); y++)
		{
			for (int x = 0; x < tileLayer->getWidth(); x++)
			{
				int tile = tileLayer->getTile(x, y);

				if (transparency && tile != 0)
				{
					setTile(x + x_, y + y_, tile);
				}
			}
		}
	}

	void TileLayer::draw(BITMAP* dest, int scrollx, int scrolly, TileSet *tileSet)
	{
		int x1 = scrollx / TILE_SIZE;
		int y1 = scrolly / TILE_SIZE;
		int x2 = (scrollx + dest->w) / TILE_SIZE;
		int y2 = (scrolly + dest->h) / TILE_SIZE;

		x1 = clamp(x1, 0, getWidth() - 1);
		y1 = clamp(y1, 0, getHeight() - 1);
		x2 = clamp(x2, 0, getWidth() - 1);
		y2 = clamp(y2, 0, getHeight() - 1);

		for (int y = y1; y <= y2; y++)
		{
			for (int x = x1; x <= x2; x++)
			{
				int dx = x * TILE_SIZE - scrollx;
				int dy = y * TILE_SIZE - scrolly;
				int tile = getTile(x, y);
				tileSet->drawTile(dest, dx, dy, tile);
			}
		}
	}
}